#include "menucontainer.h"

namespace menu
{
    void keyboardCallback(const DEVICE_EVENT &evt)
    {
        if (evt.type == DEVICE_KEYBOARD)
        {
            CKeyboard *pKeyboard(dynamic_cast<CKeyboard*>(evt.pDevice));
            if (pKeyboard->keyPressed(evt.charrKeyboardData, DIK_DOWN) ||
                pKeyboard->keyPressed(evt.charrKeyboardData, DIK_UP) ||
                pKeyboard->keyPressed(evt.charrKeyboardData, DIK_RETURN) ||
                pKeyboard->keyPressed(evt.charrKeyboardData, DIK_NUMPADENTER) ||
                pKeyboard->keyPressed(evt.charrKeyboardData, DIK_LEFT) ||
                pKeyboard->keyPressed(evt.charrKeyboardData, DIK_RIGHT))
            {
                CMenuContainer *pMenus(CMenuContainer::getInstance());
                pMenus->keyboardEvent(evt);
            }
        }
    }
}

CMenuContainer::CMenuContainer()
{
    CInputDevice *pDevice(CInputDeviceManager::getInstance()->getDevice(
        "keyboard1"));
    if (pDevice != nullptr)
    {
        pDevice->registerEventListener(&menu::keyboardCallback);
    }

    CSoundManager::getInstance()->addSound("confirm.wav");
    CSoundManager::getInstance()->addSound("select.wav");
    CSoundManager::getInstance()->addSound("change_selection.wav");
}

CMenuContainer::~CMenuContainer()
{
    CInputDevice *pDevice(CInputDeviceManager::getInstance()->getDevice(
        "keyboard1"));
    if (pDevice != nullptr)
    {
        //pDevice->unregisterEventListener(&menu::keyboardCallback);
    }

    for (map<string, CMenu*>::const_iterator pPos(m_arrMenus.begin());
         pPos != m_arrMenus.end(); ++pPos)
    {
        delete pPos->second;
    }
}

CMenuContainer *CMenuContainer::getInstance()
{
    static CMenuContainer s_instance;
    return &s_instance;
}

CMenu *CMenuContainer::addMenu(const string &szReference, float fX, float fY)
{
    CMenu *pMenu(getMenu(szReference));
    if (pMenu == nullptr)
    {
        pMenu = new CMenu(fX, fY);
        m_arrMenus.insert(std::pair<string, CMenu*>(szReference, pMenu));
    }
    return pMenu;
}

CMenu *CMenuContainer::addMenu(const string &szReference, CMenu *pMenu)
{
    m_arrMenus.insert(std::pair<string, CMenu*>(szReference, pMenu));
    return pMenu;
}

CMenu *CMenuContainer::getMenu(string szReference) const
{
    map<string, CMenu*>::const_iterator pPos(m_arrMenus.find(szReference));
    if (pPos == m_arrMenus.end())
    {
        return nullptr;
    }
    return pPos->second;
}

bool CMenuContainer::removeMenu(string szReference)
{
    map<string, CMenu*>::const_iterator pPos(m_arrMenus.find(szReference));
    if (pPos != m_arrMenus.end())
    {
        m_arrMenus.erase(pPos);
        return true;
    }
    return false;
}

void CMenuContainer::keyboardEvent(const DEVICE_EVENT &evt)
{
    vector<CMenu*> arrMenus;
    for (map<string, CMenu*>::const_iterator pPos(m_arrMenus.begin());
         pPos != m_arrMenus.end(); ++pPos)
    {
        if (pPos->second->isActive())
        {
            arrMenus.push_back(pPos->second);
        }
    }
    for (vector<CMenu*>::const_iterator pPos(arrMenus.begin());
         pPos != arrMenus.end(); ++pPos)
    {
        (*pPos)->handleInput(evt);
    }
}

void CMenuContainer::render()
{
    for (map<string, CMenu*>::const_iterator pPos(m_arrMenus.begin());
         pPos != m_arrMenus.end(); ++pPos)
    {
        pPos->second->render();
    }
}